#include <stdio.h>
#include <string.h>

#define LABEL_C
#include "label.h"
#include "core.h"
#include "calc.h"

#include "bcalls.h"
#include "flags.h"

void ClearLabelPage(int slot,int p) {
	page_labels_t* page = calcs[slot].labels.page[p];
	if ( page ) {
		int i;
		for(i=0;i<page->total_labels;i++) {
			if (page->label_array[i].name) free(page->label_array[i].name);
		}
		free(page);
	}
	calcs[slot].labels.page[p] = NULL;
}
	
	
int lookup_label(char *label) {
	int i, j;
	for (i = 0; i < calcs[gslot].labels.total_pages; i++) {
		for (j = 0; j < calcs[gslot].labels.page[i]->total_labels; j++) {
			if (!(strcasecmp(label, calcs[gslot].labels.page[i]->label_array[j].name))) {
				return calcs[gslot].labels.page[i]->label_array[j].value;
			}
		}
	}
	return -1;
}	
	
void ClearLabels(int slot) {
	int i;
	labels_t* labels = &calcs[slot].labels;
	for(i=0;i<labels->total_pages;i++) {
		ClearLabelPage(slot,i);
	}
	labels->total_pages = 0;
}
void VoidLabels(int slot) {
	int i;
	labels_t* labels = &calcs[slot].labels;
	for(i=0;i<256;i++) {
		labels->page[i] = NULL;
	}
	labels->total_pages = 0;
}

page_labels_t* GetLabelPage( int slot, int p ) {
	int i;
	labels_t* labels = &calcs[slot].labels;
	for(i=0;i<labels->total_pages;i++) {
		if (labels->page[i]->page == p) {
			return labels->page[i];
		}
	}
	
	// Otherwise create the page
	labels->page[i] = malloc(sizeof(page_labels_t));
	if (!labels->page[i]) return NULL;
	labels->page[i]->page = p;
	labels->page[i]->total_labels = 0;
	labels->total_pages++;
	return labels->page[i];
}

char* FindAddressLabel( int slot, int p, unsigned int address) {
	int i,b;
	labels_t* labels = &calcs[slot].labels;
	page_labels_t* page;

	for(i=0;i<labels->total_pages;i++) {
		if (labels->page[i]->page == p) {
			page = labels->page[i];
			for(b=0;b<page->total_labels;b++) {
				if (page->label_array[b].value == address) {
					return page->label_array[b].name;
				}
			}
		}
	}
	for(i=0;i<labels->total_pages;i++) {
		if (labels->page[i]->page == -1) {
			page = labels->page[i];
			for(i=0;i<page->total_labels;i++) {
				if (page->label_array[i].value == address) {
					return page->label_array[i].name;
				}
			}
		}
	}
	return NULL;
}
	
//-------------------------------------------
// True means label is found and is the same
//
BOOL label_search_tios(char *label,int equate) {
	int i,b;
	
	if (!label) return FALSE;

	for(i=0;bcalls[i].address != -1; i++ ) {
		if (strcasecmp(label,bcalls[i].name) == 0) {
			if (bcalls[i].address == (equate&0xFFFF) ) {
				return TRUE;
			}
		}
	}
	
	for(i=0; flags83p[i].flag != -1; i++ ) {
		if (strcasecmp(label,flags83p[i].name) == 0) {
			if (flags83p[i].flag == (equate&0xFFFF)) {
				return TRUE;
			}
		}
		for(b=0;b<8;b++) {
			if (strcasecmp(label,flags83p[i].bits[b].name) == 0) {
				if (flags83p[i].bits[b].bit == (equate&0xFFFF)) {
					return TRUE;
				}
			}
		}
	}
	return FALSE;
}
	

int labels_app_load(int slot, int app, char* fn) {
	FILE *labelFile;
	int i,length;
	char buffer[256];
	char name[256];
	unsigned int equate;
	applist_t* applist = &calcs[slot].applist;
	page_labels_t* page;
	

    if (!(labelFile = fopen(fn,"r"))) {
        puts("Error opening label files.");
        return 1;
    }

    while (!feof(labelFile)) {
		fgets(buffer,256,labelFile);
		i = 0;
		if (buffer[0] != ';')
			i = sscanf(buffer,"%s = $%04X",name,&equate);
		if (i == 2) {
			length = strlen(name);
			if (!label_search_tios(name,equate)) {
				if ( (equate&0xFFFF)>=0x4000 && (equate&0xFFFF)<0x8000) {
					if (applist->count > app) {
						i = (equate>>16)&0xFF;
						equate = (equate&0xFFFF);
						if (i <= applist->apps[app].page_count) {
							i = applist->apps[app].page-i;
							
							if ( !(FindAddressLabel(slot,i,equate)) ) {
								
								page = GetLabelPage(slot, i);
								
								i = page->total_labels;
								page->label_array[i].name = malloc(length+1);
								strcpy(page->label_array[i].name,name);
								page->label_array[i].value = equate;
								page->total_labels++;
							}
						}
					}
				} else {
					equate = (equate&0xFFFF);
					if ( !(FindAddressLabel(slot,-1,equate)) ) {
						page = GetLabelPage(slot,-1);
						i = page->total_labels;
						page->label_array[i].name = malloc(length+1);
						strcpy(page->label_array[i].name,name);
						page->label_array[i].value = equate;
						page->total_labels++;
						printf("%s = %X \n",page->label_array[i].name,page->label_array[i].value);
					}
				}
			}
		}
    }
    fclose(labelFile);
    return 0;
}
    
/*
void ImportBcalls(char* fn) {
	int i,address;
	char string[256],tmp[32];
	FILE* infile;
	
	infile = fopen(fn,"r");
	
	if (!infile) {
		puts("COuld not open bcall file");
		return;
	}
	for(address=0;address<65536;address++) {
		for(i=0;i<32;i++) bcalls[address][i] = 0;
	}		
	while( !feof(infile) ) {
		fgets(string,256,infile);
		i = sscanf(string,"%s = $%04X",tmp,&address);
		if (i == 2) {
			strcpy(bcalls[address],tmp);
		}
	}
	fclose(infile);
}
*/
char* FindBcall(int address) {
	int i;
	for(i=0;bcalls[i].address != -1; i++ ) {
		if (bcalls[i].address == address) {
			return bcalls[i].name;
		}
	}
	return NULL;
}


void FindFlags(int flag,int bit, char **flagstring, char **bitstring) {
	int i,b;
	for(i=0; flags83p[i].flag != -1; i++ ) {
		if (flags83p[i].flag == flag) {
			for(b=0;b<8;b++) {
				if (flags83p[i].bits[b].bit == bit) {
					*flagstring = flags83p[i].name;
					*bitstring  = flags83p[i].bits[b].name;
					return;
				}
			}
		}
	}
	*flagstring = NULL;
	*bitstring  = NULL;
}
	
	
	
	
	

